Translated by visionNoob, KNU https://github.com/insurgent92/CS231N_17_KOR_SUB
좋은 아침입니다. 12시 3분이군요. 수업을 진행하겠습니다.
CS231n 12강입니다.
오늘은 CNN의 시각화와 이해에 대해서 배워볼 것입니다.
12강은 이미지 자료가 아주 많아서 아주 재미있는 수업이 될 것입니다.
제가 가장 좋아하는 강의입니다.
우선 몇 가지 공지사항을 전달해 드리겠습니다.
프로젝트는 잘 진행하고 계신가요? 오늘 밤 까지 Canvas에 마일스톤을 제출해 주셔야 합니다.
그리고 현재 중간고사를 채점 중입니다.
아마도 채점 결과는 Gradescope를 통해서 이번 주 이내로 확인해 보실 수 있을 것입니다.
지난 주에 여러분께서 Gradescope 가입과 관련해서 많이 혼란스러우셨을 것입니다.
Piazza에서 이와 관련된 질문들을 많이 받았습니다.
중간고사 채점 결과를 Gradescope를 통해서 발표하기로 결정했습니다. 관련 메일을 받으시면 잘 확인해 주시기 바랍니다.
그리고 지난 주 금요일에 과제 3이 출제 되었습니다.
과제 3은 지난 주 금요일부터 1주일 후인 26일 까지 입니다.
과제3은 지난 해와 비교해서 완전히 달라졌습니다.
과제3을 예정보다 늦게 출제해 드려서 사과의 말씀 드립니다.
하지만 과제3은 아주 재밌을 것입니다. 오늘 강의에서 배운 내용들을 실제로 구현하게 될 것입니다.
과제3을 하시려면 PyTorch/Tensor Flow 중에서 선택하시면 됩니다.
이번 과제가 여러분들에게 의미있는 경험이 되었으면 좋겠습니다.
그리고 주말 동안 많은 분들이 HyperQuest 활동을 해주셨습니다.
아주 놀라웠습니다. 리더보드가 어제 생겼는데
많은 분들이 Deep learning/ Neural network을 학습시키는 스킬들을 마음껏 뽐내 주셨습니다. 대단합니다.
HyperQuest의 많은 분들의 성원 가운데 마일스톤 제출기한이 HyperQuest와 겹치는 부분이 있었기 때문에
Extra credit을 드리는 HyperQuest 마감일을 일요일까지 연장하기로 했습니다.
따라서 일요일 까지 HyperQuest를 12회 이상 실행하신 모든 분들에게 extra credit을 지급할 예정입니다.
그리고 리더보드의 상위권에 위치하신 분들은 조금 더 많은 credit을 받게될 것입니다.
HyperQuest에 많은 관심에 감사드리며 아주 뜻깊은 시간인 것 같습니다.
마지막 공지사항은 poster session 관련 공지입니다.
6월 6일에 poster session이 있습니다.
6월 6일이 거의 확정일 것입니다. 정확한 시간은 기억이 안나지만, 6월 6일은 확실합니다.
종강 후 여행이나 인턴쉽을 준비하고 있는 많은 분들이 poster session 일정을 문의해 주셨습니다.
poster session은 6월 6일입니다.
공지사항에 대한 문의사항 있으십니까? 없으면 수업 진행하겠습니다.
지난 시간에는 다양한 Computer Vision Tasks를 살펴보았습니다.
우선 Semantic segmentation을 배웠습니다. 입력 이미지의 모든 픽셀에 레이블링을 하는 문제였습니다.
하지만 Semantic Segmentation은 이미지 내의 객체들을 구분할 수 없었습니다.
그리고 Classification + Localization을 배웠습니다.
이 문제는 이미지에 레이블을 부여하는 것 뿐만 아니라 객체의 정확한 위치의 BBox도 알아내야 했습니다.
Classification + Localization 문제에서는 이미지 내에 알아내야 하는 객체의 수가 정해져 있었습니다.
Classification + Localization을 응용해서 Pose recognition을 할 수 있었습니다.
사람의 관절의 위치를 regression 문제로 푸는 방법이었죠
Object Detection도 배웠습니다. 개, 고양이 처럼 고정된 category labels이 있었습니다.
그리고 이미지 내에 모든 객체의 위치에 BBox를 그려 넣어야 했습니다.
Object Detection은 Classification + Localization 문제와는 다른 문제였습니다.
Object Detection 문제에서는 이미지 내에 객체의 수가 얼마나 있는지 미리 알 수 없었습니다.
R-CNN, Fast R-CNN, Faster R-CNN 패밀리를 배웠습니다. 그리고 single shot detection 도 배웠죠(YOLO, SSD)
그리고 Instatnce Segmentation에 대해서도 간단하게 배워 보았습니다.
Semantic segmentation과 Object Detection을 결합시킨 방법이었습니다.
Instance Segmentation의 목표는 우선 우리가 관심있는 카테고리에 속하는 모든 객체를 찾아내고
각 객체가 속하는 픽셀을 레이블링하는 문제였습니다.
가령 이 예제에서는 2마리의 개와 1마리의 고양이가 있으며 객 객체가 속하는 픽셀을 레이블링해야 합니다.
지난 시간에도 재미있는 Tasks들을 많이 다루긴 했지만 여러분이 프로젝트에 추가할만한 아주 많은 것들이 존재합니다.
오늘은 주제를 조금 바꿔보도록 하겠습니다.
과연 convolutional networks 내부에서는 어떤 일이 일어나고 있는 것일까요?
지금까지는 CNN을 어떻게 학습시킬 것인지를 배웠습니다.
그리고 다양한 문제를 풀기 위해서 CNN 아키텍쳐를 어떻게 설계하고 조합해야하는지를 배웠습니다.
자 이제 여러분이 해 볼만한 질문은 바로 CNN의 내부는 어떻게 생겼을지 입니다.
CNN은 이런 문제들을 어떻게 해결하는 것일까요?
CNN이 어떤 종류의 Features를 찾고있는 것일까요?
이와 같은 질문들 말입니다.
지금까지는 ConvNets을 Black box라고 생각했습니다.
CNN의 한 쪽에서는 입력 이미지가 들어갑니다.
그리고 Conv Layers를 거치면서 아주 다양한 변환을 거치게 됩니다.
결국 CNN의 출력 값은 우리가 이해하고 해석할 수 있는 Class scores의 형태로 나오는 것입니다.
Class scores 뿐만 아니라 Bounding Box의 위치, Labeled pixels 와 같은 형태의 출력도 있을 것입니다.
그럼 CNN의 중간 과정에서는 무슨 일이 일어나는 것일까요?
CNN이 입력 이미지에서 찾고있는 것은 무엇일까요?
ConvNets은 어떻게 동작할까요? CNN이 도대체 이미지에서 어떤 종류의 것들을 찾고있는 걸까요?
CNN의 내부를 분석하려면 어떤 테크닉이 필요할까요?
우선 가장 만만하게 접근해 볼 수 있는 것은 첫 번째 Layer 입니다.
우선 AlexNet의 예시를 살펴보겠습니다.
AlexNet의 첫 번째 Conv Layers에는 많은 필터들이 있습니다.
AlexNet의 각 Conv filter는 3 x 11 x 11의 형태를 취하고 있습니다.
Conv filters는 sliding window로 이미지를 돕니다.
그리고 이미지의 일부 영역과 내적을 수행합니다.
이렇게 필터의 가중치와 내적한 결과가 첫 번째 Conv Layer의 출력입니다.
AlexNet의 첫 번째 레이어에는 64개의 filter가 있습니다.
첫 번째 Conv Layer는 입력 이미지와 직접 내적을 수행하기 때문에
이 필터를 단순히 시각화시키는 것 만으로도 이 필터가 이미지에서 무엇을 찾고 있는지 알아낼 수 있습니다.
AlexNet의 11x11x3 필터는 11x11x3 rgb 이미지로 쉽게 시각화할 수 있습니다.
필터가 총 64개 이므로 64개의 11x11 이미지를 시각화시킬 수 있습니다.
지금 보시는 이미지는 PyTorch Model zoo에서 가져온 pretrained model의 필터들입니다.
AlexNet, ResNet-18, ResNet-101,DenseNet-121 의 첫 번째 Conv filter의 가중치들 입니다.
이를 통해서 이 필터들이 무엇을 찾고있는지 알 수 있습니다.
우선 가장 많이 찾는 것은 엣지성분 입니다. 흰/검으로 길게 늘어선 필터들이 보이실 것입니다.
다양한 각도와 위치에서의 보색(oppising colors)도 보입니다. 가령 초록색과 분홍색처럼 말이죠
주황색과 파랑색의 보색도 보입니다.
학습된 필터를 살펴보면 첫 강의에서 살펴본 hubel and wiesel의 실험이 떠오릅니다.
인간의 시각 체계에서도 Oriented edges를 감지한다고 알려져 있습니다. 초기 레이어에서 말이죠
CNN의 첫 번째 layer에서도 비슷한 일이 일어나는 것 같습니다.
흥미롭게도, CNN을 어떤 모델/데이터로 학습하건 간에 첫 번째 레이어는 전부 다 이런 식으로 생겼다는 점입니다.
입력 이미지에서 oriented edges 라던지 보색(opposing colors) 같은 것들을 찾는 것입니다.
질문 있나요?
네. 이 이 이미지들을 CNN Layer의 학습된 가중치 입니다.
질문은 "필터의 가중치를 시각화한다고 해서 필터가 무엇을 찾고있는지 알 수 있는지" 입니다.
이는 Templete Matching 이나 내적을 생각하시면 됩니다.
가령 여러분이 Templete vecter를 가지고있다고 해봅시다.
이 Templete Vector와 임의의 데이터를 내적해서 어떤 Scaler output을 계산합니다.
필터 값을 가장 활성화시키는 입력을 생각해보면 입력 값고 필터의 가중치 값이 동일한 경우입니다.
내적을 생각해보면, 내적 값을 최대화 시키려면 동일한 값 두 개를 내적하는 것입니다.
그렇게 때문에 첫 번째 레이어의 가중치를 시각화시키면 첫 번째 레이어가 무엇을 찾고 있는지 알 수 있는 것입니다.
그리고 이 첫 번쨰 레이어는 Convolutional Layer 입니다.
이미지를 입력으로 받는 CNN은 일반적으로 첫 번째 레이어가 Conv Layer입니다.
다음 질문은 "네트워크의 중간에도 이런 시각화를 동일하게 적용할 수 있는지" 입니다.
바로 다음 슬라이드가 그 내용입니다. :D
앞서 했던 동일한 시각화 기법을 중간 Conv Layers에 적용하면, 우리가 보고 해석하기 더 어렵습니다.
지금 보시는 것이 동일한 시각화 기법을 적용한 것입니다.
현재 보시는 슬라이드는 우리 웹사이트에 있는 작은 ConvNets demo network입니다.
이 네트워크에서 첫 번째 레이어는 7 x 7 필터 16개 입니다.
앞선 슬라이드에서 시각화로 보여드렸던 첫 번째 레이어와 동일합니다.
이제는 두 번째 레이어의 가중치들을 살펴봅시다. 두 번째 레이어까지는 수 차례 Conv & ReLU를 거쳐야 합니다.
두 번째 Conv Layer는 16채널의 입력을 받습니다.
그리고 20개의 7x7 conv filters가 있습니다.
이 필터들은 직접적으로 이미지의 형태로 시각화시킬 수 없다는 문제점이 있습니다.
어쨌든 시도는 해볼 수 있겠죠
이 예시에서는 입력은 16 depth를 가지고 있습니다.
그리고 Conv filters의 사이즈는 7 x 7 x 16 입니다. 이런 필터가 20개 있습니다.
여기서 문제점은 이 필터들을 직접 살펴보는 것 만으로는 이해할만한 정보를 얻기 힘들다는 점입니다.
여기에 (Layer 2 weights) 두 번째 레이어를 시각화 시켰습니다. 16 x 7 x 7 필터를 시각화하기 위해서는
16개의 7 x 7 grayscale images로 나눠서 표현해야 합니다.
중간에 보이시는 Gray scale 이미지들이 바로 두 번째 레이어의 각 필터들의 가중치입니다.
두 번째 레이어의 출력이 총 20개 이므로 "7 x 7 이미지 16개"가 총 20개 있습니다.
두 번째 레이어의 convolutional filters를 이미지로 시각화 해보면 이런 식의 특별한 구조들을 보실 수 있습니다.
그런데 아무리 자세히 봐도 이 필터가 무엇을 찾고 있는건지 적당한 Intuition을 얻기란 힘듭니다.
아무리 봐도 잘 모르겠는 이유는 이 필터들은 이미지와 직접 연결되어 있지 않기 떄문입니다.
두 번째 레이어의 필터들은 첫 번째 레이어의 출력과 연결되어 있습니다.
따라서 우리가 시각화한 내용은 "두 번째 레이어의 결과를 최대화시키는 첫 번째 레이어의 출력 패턴이 무엇인지" 입니다.
하지만 이미지의 관점에서 첫 번째 레이어의 출력이 어떻게 생겼는지 감을 잡고 해석하기한 쉽지 않습니다.
따라서 네트워크의 중간 레이어의 필터들이 무엇을 찾고있는지를 알아내려면 조금 더 fancy한 기법이 필요합니다.
질문있나요?
앞서 슬라이드에 있던 이미지들은 0-255 의 범위로 가중치를 normalize한 것입니다.
실제 가중치들은 범위가 정해져있지 않습니다. 하지만 시각화를 위해서라면 스케일을 조정해야 합니다.
그리고 필터만 시각화한 것이지 Bias는 고려하지 않았습니다. 따라서 이 시각화 결과를 있는 그대로 믿으면 안됩니다.
자 이제는 마지막 레이어를 살펴봅시다. CNN의 마지막 레이어를 가지고 놀어봅시다.
CNN의 마지막 레이어는 1000개의 클래스 스코어가 있습니다. 이는 학습 데이터의 predicted scores를 의미합니다.
이 마지막 레이어 직전에는 Fully Connected Layer가 있습니다.
가령 AlesNet의 마지막 레이어는 이미지를 표현하는 4096-dim 특징벡터를 입력으로 최종 Class scores를 출력합니다.
CNN의 마지막 레이어에서 어떤 일이 일어나는 지를 알아보는 것도 시각화의 한 방법이 될 수 있습니다.
이 방법은 많은 이미지로 CNN을 돌려서 각 이미지에서 나온 4096-dim 특징 벡터를 모두 저장힙니다.
앞선 방법에서는 첫 번째 Conv Layer를 시각화시켰지만 이제는 마지막 Hidden Layer를 시각화시킬 것입니다.
여기에서 시도해볼 수 있는 방법 중 하나는 Nearest Neighbor를 이용한 방법입니다.
맨 왼쪽의 이미지는 Lecture 2에서 본 적 있으실 것입니다.
CiFAR-10 데이터들의 "이미지 픽셀 공간" 에서의 Nearest neighbors 였습니다.
CIFAR-10으로 한 결과를 보시면 유사한 이미지를 잘 찾아내는 것을 알 수 있습니다.
맨 왼쪽 열이 CIFAR-10 으로 학습시킨 이미지입니다. 오른쪽 5열의 이미지는 Testset이죠
가령 두 번째 행에 있는 흰색 강아지의 예를 들어보겠습니다.
픽셀 공간에서의 Nearest neighbors는 흰색 덩어리가 있으면 가깝다고 생각할 것입니다. 굳이 개가 아니라도 말이죠
이런 식으로 거리가 가까운 이미지들을 시각화해 보는 방법도 시각화 기법이 될 수 있습니다.
다만 픽셀 공간에서 Nearest neighbors를 계산하는 것이 아니라 CNN에서 나온 4096-dim 특징 벡터 공간에서 계산합니다.
오른쪽에 예제가 몇 가지 있습니다.
맨 왼쪽 열은 ImageNet Classification Dataset의 Test Set입니다.
그리고 나머지 열 들은 AlexNet의 4096-dim 특징벡터에서 계산한 nearest neighbors 결과입니다.
이 결과를 보면 확실히 픽셀 공간에서의 nearest neighbors와는 아주 다릅니다.
"특징 공간에서의 nearest neighbors"의 결과를 보면 서로 픽셀 값의 차이가 큰 경우도 있습니다.
서로 픽셀 값의 차이는 커도 특징 공간 내에서는 아주 유사한 특성을 지닌다는 것을 알 수 있습니다.
가령 여기 두번째 줄에 코끼리의 예를 살펴봅시다. 코끼리는 왼쪽에 서있고 그 뒤에는 풀밭이 있습니다.
테스트 셋의 3번째로 가까운 이미지를 살펴보면 코끼리가 오른쪽에 서 있습니다.
아주 흥미롭습니다. 코끼리가 왼편에 서 있는 이미지와 오른편에 서 있는 이미지의 픽셀 값은 완전히 다를 것이기 때문입니다.
하지만 네트워크가 학습한 특징 공간 내에서는 두 이미지는 아주 아까워집니다.
이는 네트워크가 학습을 통해서 이미지의 semantic content한 특징들을 잘 포착해 낸 결과입니다.
아주 놀라운 일이죠. 이처럼 Nearest neighbor를 통한 시각화 기법은 어떤 일이 일어나는지 살펴보기에 아주 좋습니다.
[학생이 질문]
기본적인 supervised learning 과정에서는 특징공간에서 서로 유사해야한다는 Loss는 없습니다.
특징 공간에서 서로 유사해야한다고 말해주지 않았는데도 결국은 서로 가까워 진 것입니다.
하지만 사람들이 "triplet/contrastive loss" 를 네트워크가 추가시켜서 학습하기도 합니다.
이 losses를 통해 특징 공간에서의 계산이 가능하도록 가정과 제약조건을 마지막 레이어에 추가하는 것입니다.
하지만 AlexNet의 경우에는 그런 장치가 없습니다.
문제는 가장 가까운 것이 무엇인지...
질문은 "마지막 레이어에 nearest neighbor를 적용하려면 어떻게 해야하는지" 입니다.
우선 이미지를 네트워크에 통과시킵니다.
뒤에서 두번째에 있는 히든 레이어는 4096-dim 벡터입니다.
네트워크이 마지막 단에는 FC-Layer가 있었습니다.
자 그럼 각 이미지들에 해당하는 4096-dim 벡터들을 전부 다 저장해 놓습니다.
그리고 저장된 4096-dim 벡터들을 가지고 nearest neighbors를 계산합니다.
수업이 끝나고 다시한번 말씀드리죠
최종 레이어에서 어떤 일이 벌어지는지를 시각화하고자 할 때 "차원 축소"의 관점으로 볼 수도 있습니다.
CS229를 수강하신 분들이라면 PCA에 대해서 들어본 적 있으실 것입니다.
PCA는 4096-dim 과 같은 고차원 특징벡터들을 2-dim 으로 압축시키는 기법입니다.
이 방법을 통해서 특징 공간을 조금 더 직접적으로 시각화시킬 수 있습니다.
Principle Component Analysis(PCA) 로 이런 일을 할 수는 있지만 t-SNE라는 알고리즘이 더 파워풀합니다.
t-SNE는 t-distributed stochastic neighbor embeddings 이라는 뜻입니다.
많은 사람들이 특징공간을 시각화하기 위해서 사용하는 PCA보다는 조금 더 강력한 방법입니다.
여기 t-SNE의 예시가 있습니다.
MNIST를 t-SNE dimensionality reduction 를 통해 시각화한 모습입니다.
MNIST는 0부터 9까지로 이루어진 손글씨 숫자 데이터셋입니다.
MNIST의 각 이미지는 Gray scale 28x28 이미지입니다.
여기에서는 t-SNE가 MNST의 28x28-dim 데이터를 입력으로 받습니다(raw pixels). 그리고 2-dim으로 압축합니다.
그리고 압축된 2-dim 을 이용해서 MNIST를 시각화합니다.
t-SNE로 MNIST를 시각화해보면 이런 식으로 자연스럽게 군집화된 모습을 볼 수 있습니다.
각 군집이 MNIST의 각 숫자를 의미합니다.
이런 식의 시각화 기법을 ImageNet을 분류하려고 학습시킨 네트워크의 마지막 레이어에도 적용해볼 수 있습니다.
조금 더 자세히 말씀드리자면 엄청나게 많은 이미지들을 네트워크에 통과시킵니다.
그리고 각 이미지에 대해서 최종 단의 4096-dim 특징 벡터들을 기록합니다.
그러면 4096-dim 특징 벡터들을 아주 많이 모을 수 있을 것입니다.
그리고 이 특징벡터들에 t-SNE을 적용하면 4096-dim에서 2-dim으로 압축됩니다.
이를 통해 2-dim 특징 공간의 각 grid에 압축된 2-dum 특징들이 시각화시킵니다.
이를 통해 학습된 특징 공간의 기학적인 모습을 어렴풋이 추측해 볼 수 있습니다.
슬라이드의 이미지가 잘 안보이실 것입니다. 온라인에서 고해상도로 다시한번 살펴보시기 바랍니다.
한번 살펴보자면 좌하단의 초록초록한 군집을 볼 수 있습니다. 이 곳에는 다양한 종류의 꽃들이 있습니다.
또 다른 곳들에는 다양한 종류의 개들이 모여있고, 다양한 동물들끼리 모여있고, 다양한 지역들이 모여있습니다.
이를 통해 우리가 학습시킨 특징 공간에는 일종의 불연속적인 의미론적 개념(semantic notion)이 존재하며
t-SNE을 통한 dimensionality reduction version의 특징 공간을 살펴보며 그 공간을 조금이나마 느낄 수 있습니다.
질문 있나요?
한 이미지당 서로 다른 세 가지 정보가 존재합니다.
1: 우선 (픽셀로 된) 원본 이미지가 있습니다.
2: 그리고 4096-dim 벡터가 있습니다. (fc-layer의 출력)
3: 그리고 t-SNE를 이용해 4096-dim 벡터를 2-dim 벡터로 변환시킨 값이 있습니다.
결국 원본 이미지를 CNN으로 4096-dim으로 줄이고 이를 다시 t-SNE로 2-dim으로 줄였다고 보시면 되겠습니다.
질문 있나요?
질문은 t-SNE로 만든 이 2차원 공간에서 대강 얼마나 많은 데이터들을 표현할 수 있는지 입니다.
정확히 얼마나 표현할 수 있는지 확신하긴 어렵습니다. t-SNE는 비선형 차원축소 기법이라 상당히 복잡한 성격을 지닙니다.
다시 한번 확인해 봐야 겠지만 정확히 얼마나 표현할 수 있을지 잘 모르겠습니다.
질문 있나요?
질문은 "FC-layer가 아닌 더 상위 레이어에서도 이와 같은 시각화가 가능한지" 입니다.
네 가능합니다. 하지만 안타깝게도 우리 강의자료에는 없네요. 죄송합니다.
질문있나요?
질문은 "이미지들이 차원축소 과정에서 이미지들이 서로 겹치지는 않은지" 입니다.
네 물론 겹칠 수 있습니다.
regular grid를 기준으로 nearest neighbor, 즉 각 grid point에 가장 가까운 이미지를 뽑아냅니다.
따라서 이 시각화 기법이 특징 공간 분포의 모양을 보여주는 것은 아닙니다.
t-SNE는 분포 자체를 보고자 함은 아닙니다. 그러한 특성을 다루는 몇 가지 다른 시각화 기법들이 존재합니다.
네트워크의 중간에서 뽑은 특징들을 가지고 해볼 수 있는 다른 것들도 한번 살펴보겠습니다.
앞서, 중간 레이어에 있는 가중치를 시각화한다고 해도 이를 해석하기는 쉽지 않다고 말씀드렸습니다.
하지만 중간 레이어의 가중치가 아니라 Activation map을 시각화 해보면 일부 해석할 수 있는 것들을 볼 수 있습니다.
다시 AlexNet의 예시를 살펴보겠습니다.
AlexNet의 conv5의 특징은 128 x 13 x 13-dim tensor입니다.
이 tensor는 128개의 13x13 2-dim gird로 볼 수 있습니다.
따라서 이 13 x 13 ( x 1) 특징 맵을 그레이스케일 이미지로 시각화해 볼 수 있습니다.
이를 시각화해보면 conv layer가 입력에서 어떤 특징을 찾고있는지를 짐작해볼 수 있습니다.
지금 보시고있는 툴은 Jason Yasenski가 만든 아주 멋진 툴로 여러분도 다운로드받으실 수 있습니다.
지금 동영상으로는 보여드리지 않겠지만 이 분의 웹사이트에 접속하시면 보실 수 있습니다.
여기에서는 웹캠으로 받은 영상을 CNN에 통과시킵니다.
그리고 실시간으로 중간의 각 특징 맵들을 시각화시켜서 각 레이어들이 무엇을 찾고있는지를 짐작해볼 수 있습니다.
이 예시의 입력 이미지는 카메라 앞에 사람이 있는 영상입니다.
중간 특징들의 대부분은 noisy하고 볼만한 게 없지만
제가 초록색으로 표시한 특징맵을 보시면, (왼쪽에 더 크게 확대된 이미지도 있습니다.)
이 특징맵은 사람의 얼굴에 활성화되는 것 같아 보입니다. 아주 재미있습니다.
이 특징맵을 통해서, 분명 네트워크의 어떤 레이어에서는 사람의 얼굴을 찾고있는지 모른다는 것을 알 수 있습니다.
아주 놀라운 발견입니다.
질문있나요?
질문은 "완전 새까만 특징 맵들"은 "Dead ReLU" 인지 입니다. 용어에 주의해야 합니다.
대게 "Dead ReLU"라고 함은 모든 학습 데이터셋에 대해서 "Dead(활성화 되지 않음)" 을 의미합니다.
이 예시의 경우에는 "특정 입력" 에 대해서 활성화되지 않았을 뿐입니다.
질문있나요?
질문은 "만약 ImageNet에 사람의 얼굴이 없다면 어떻게 네트워크가 사람의 얼굴을 인식할 수 있는지" 입니다.
ImageNet의 사람은 아주 많이 등장합니다.
물론 ImageNet Classification Chanllenge에의 1000개의 카테고리에 "사람"은 없습니다.
많은 이미지들에 사람이 등잘하며, 다른 카테고리를 분류하더라도 사람이 등장한다는 특성은 유용한 신호일 수 있습니다.
그리고 이는 정말 대단한 결과입니다. 분류 문제를 풀기에 유용한 특징들을 알아서 학습한 것이기 떄문입니다.
가령 고양이만 분류하라고 했을 뿐인데, 고양이를 분류할 때 사람이 유용한 특징이라면 알아서 학습하는 것입니다. 대단한 것이죠.
질문있나요?
네트워크의 입력은 3 x 224 x 224 입니다. 그리고 여러 레이어를 통과할 것입니다.
각 레이어는 3차원의 값을 반환합니다. (width x height x depth)
이 3차원 덩어리(chunk)가 바로 네트워크 레이어가 출력하는 값입니다.
그리고 이 3차원 덩어리를 "activation volume" 이라고 합니다.
그리고 이 덩어리를 하나씩 잘라내면(slice) 그것이 바로 activation map 입니다.
앞어 질문은 "입력 이미지가 K x K 라면 activation map이 K x K 인지" 였습니다.
그렇지 않습니다. 네트워크 중간에 pooling 과 같은 sub sampling 과정이 있을 수 있기 때문입니다.
하지만 일반적으로 activation map의 크기는 입력 이미지와 선형적인 관계를 갖습니다.
자 그래서 중간 특징들을 시각화시킬 수 있는 또 다른 방법이 있습니다.
어떤 이미지가 들어와야 각 뉴런들의 활성이 최대화되는지를 시각화해보는 방법입니다.
이 예시에서도 다시 한번 AlexNet의 conv5 layer를 사용하겠습니다.
이 활성화 볼륨 각각을 기억하십시오.
AlexNet의 conv5는 128 x 13 x 13 한 덩어리의 activation volume을 갖습니다.
우리는 이제 128개의 채널 중에 하나를 뽑을 것입니다. 여기에서는 17번째 채널을 선택했군요
그리고 많은 이미지들을 CNN에 통과시킵니다.
그리고 각 이미지의 conv5 features를 기록해 놓습니다.
그리고나서 어떤 이미지가 17번째 특징 맵을 최대로 활성화시키는지를 살펴봅니다.
그리고 현재 이 뉴런은 convolutional layer 입니다. 따라서 receptive field가 작은 편이죠
각 뉴런이 전체 이미지를 보고있지는 않습니다. 이미지의 일부만을 보고있죠
따라서 특정 레이어의 특징을 최대화시키는 이미지의 일부분(pathes)을 시각화시킬 것입니다.
그리고 특정 레이어의 활성화 정도를 기준으로 패치들을 정렬시키면 되겠습니다.
자 여기 오른쪽에 예시가 있습니다. 이 네트워크의 이름은 "fully.." 사실 어떤 네트워크인지는 크게 중요하진 않습니다.
어쨌든 여기에 지금 보이는 패치들이 바로 해당 레이어의 활성을 최대화시키는 패치들입니다.
각 행에 있는 패치들이 하나의 뉴런에서 나온 것입니다.
각 패치들은 데이터셋에서 나온 패치들을 정렬한 값들이고
이 패치들이 해당 뉴런의 활성을 최대화시키는 패치들입니다.
패치의 특징을 통해서 해당 뉴런이 무엇을 찾고있는지 짐작해 볼 수 있습니다.
가령 맨 윗 행을 보시면 어떤 동그란 모양을 찾고있다는 것을 알 수 있습니다.
눈 같은 것들이죠. 눈이 많네요. 그리고 파란색 동그란 패치도 있군요
이로 미루어, 네트워크 레이어의 어떤 뉴런은 입력 영상에서 어떤 푸르스름하고 둥근 물체를 찾고있는 것 같습니다.
그리고 여기 중간에 보시면 뉴런이 다양한 색상의 문자를 찾는 뉴런도 있습니다.
또는 다양한 colors & orientations을 가진 휘어진 엣지를 찾는 뉴런이 있다는 것도 알 수 있습니다.
제가 여기에서 용어를 조금 느슨하게 사용한 감이 있습니다.
한 뉴런은 conv5 activation map의 하나의 scaler 값을 의미합니다.
conv5 는 convolutional layer 이기 때문에 한 채널안의 모든 뉴런들은 모두 같은 가중치를 공유합니다.
각 채널 당 하나의 conv filter가 있고 이에 상응하는 많은 뉴런들이 있습니다.(activation map)
Convolution의 특성 상 우리는 앞서 보여드린 patch들을 이미지의 모든 곳에서 추출해 낼 수 있습니다.
그리고 밑의 예시들은 동일 네트워크의 더 깊은 레이어에서 뉴런들을 최대로 활성화시키는 패치들입니다.
이들은 더 깊은 레이어로부터 왔기 때문에 Receptive field가 훨씬 더 넓습니다.
이들은 입력 영상에서 훨씬 더 큰 patch들을 기준으로 찾고 있습니다.
실제로 예시들을 살펴보면 입력 이미지에서 더 큰 구조들(structures)을 찾고있음을 알 수 있습니다.
두 번째 행을 살펴보면 이는 사람, 또는 사람의 얼굴을 찾고 있는것 같아 보입니다.
세 번째 행은 카메라의 일부분을 찾고 있는듯 합니다. 이처럼 조금 더 큰 것들을 찾고 있는 것입니다.
그리고 우리는 조금 더 재밌는 실험을 해볼 수 있습니다. 이는 Zeiler and Fergus가 ECCV'14에 발표한 논문입니다.
이 논문은 "occlusion experiment" 에 관한 논문입니다.
이 실험에서 알고자하는 것은 입력의 어떤 부분이 분류를 결정짓는 근거가 되는지에 관한 실험입니다.
우선 입력 이미지를 받습니다. 가령 이 예시의 경우는 코끼리입니다.
그리고 이미지의 일부를 가립니다. 그리고 가린 부분을 데이터셋의 평균 값으로 채워버립니다.
그리고 가려진 이미지를 네트워크에 통과시키고 네트워크가 이 이미지를 예측한 확률을 기록합니다.
그리고 이 가림 패치( occluded patch)를 전체 이미지에 대해 돌아가면서(slide) 같은 과정을 반복합니다.
오른쪽의 히트맵은 이미지를 가린 patch의 위치에 따른 네트워크의 예측 확률의 변화를 의미합니다.
이 실험의 아이디어는, 만약 이미지의 일부를 가렸는데 네트워크의 스코어의 변화가 크게 발생한다면
가려진 바로 그 부분이 분류를 결정짓는데 아주 중요한 부분이었다는 사실을 짐작할 수 있는 것입니다.
여기에 "occlusion experiment"을 수행한 세 가지 예시가 있습니다.
가장 밑의 Go-kart의 예시를 살펴봅시다.
빨간색 지역은 확률 값이 낮고, 노란색 지역은 확률 값이 높음을 의미합니다.
앞쪽의 Go-kard를 가렸을 때 Go-kart에 대한 확률이 아주 많이 감소함을 볼 수 있습니다.
이를 통해 네트워크가 분류를 결정할 때 실제로 go-kart를 아주 많이 고려한다는 사실을 알 수 있습니다.
질문 있나요?
질문은 "배경의 경우는 어떻게 된 것인지" 입니다. (go-kart 이미지의 배경을 가려도 확률이 감소)
현재 이미지가 너무 작아서 잘 안보이실 수도 있습니다만 뒷쪽 배경에 Go-kart 트랙과 다른 Go-kart들이 있습니다.
제 생각에는 뒷쪽의 go-kart를 가리는 경우에도 점수에 영향을 미치는 것으로 사료됩니다.
또는 수평선(horizon)의 영향일지도 모르겠습니다. Go-kart를 검출하는데 수평선이 유용한 특징일지도 모릅니다.
사실은 이렇게 해석하기 힘든 경우도 있습니다. 어쨌든 이 방법도 아주 훌륭한 시각화 방법입니다.
질문 있나요?
첫 번째 질문이 뭐였죠?
이 예제의 경우에 이미지 한장에 대해서 현재 이미지의 모든 부분을 조금씩 가려본 것입니다.
두 번 질문은 "이 시각화 방법이 학습에 어떻게 유용한지" 입니다.
학습 하는데 직접적으로 유용하지는 않습니다. 여기에서 얻는 정보를 학습 과정에 집어 넣을 수는 없습니다.
다만 "사람"이 네트워크가 무엇을 하고 있는지를 이해할 수 있는 도구일 뿐입니다.
결국 이런 시각화는 네트워크의 성능을 높히려는 목적이 아니라 "여러분이 이해" 함이 목적입니다.
그리고 이와 관련된 또 다른 아이디어가 있습니다. "Saliency Map" 과 관련된 아이디어입니다.
여러분이 앞으로 과제에서 보게될 것입니다.
이 경우에도 같은 질문이 있습니다.
입력 이미지가 들어옵니다. 이 경우에는 "개" 입니다. 그리고 이 이미지를 "개" 라고 예측했을 떄,
우리가 알고싶은 것은 네트워크가 픽셀들을 보고서 이미지를 "개" 라고 분류했는지 입니다.
앞서 특정 픽셀을 가리는(masking) 방법도 있었습니다만 Saliency Maps은 조금 다른 접근법을 취합니다.
이 방법은 몇해 전 Karen Simonenian의 논문에서 나온 비교적 간단한 방법입니다.
이 방법은 입력 이미지의 각 픽셀들에 대해서, 예측한 클래스 스코어의 그레디언트를 계산하는 방법입니다.
이 방법은 일종의 "1차 근사적 방법"으로 어떤 픽셀이 영향력있는지를 알려줍니다.
입력 이미지의 각 픽셀에 대해서, 우리가 그 픽셀을 조금 바꿨을 때 클래스 스코어가 얼마나 바뀔까요?
이 질문은 어떤 픽셀이 "개"를 분류하는데 있어서 어떤 픽셀들이 필요한지알 수 있는 또 다른 방법이 될 수 있습니다.
이 방법을 통해 "개" 이미지의 Saliency map을 만들어보면 "개"의 윤곽이 나타남을 알 수 있습니다.
이는 네트워크가 이미지에서 어떤 픽셀들을 찾고 있는지를 짐작할 수 있습니다.
이 방법은 다른 이미지들에도 적용해보면 네트워크가 올바른 지역을 보고있다는 것을 알 수 있습니다.
좀 위안이 되는 것이죠
질문 있나요?
질문은 "사람들이 Saliency Maps을 semantic segmentation에도 사용하는지" 입니다.
네 맞습니다. (웃음) 여러분들은 정말 최고입니다.
semantic segmentation은 Karen의 논문에 또 다른 주제로 실려있습니다.
아이디어, segmentation 레이블 없이 Saliency Maps 만 가지고 semantic segmentation을 수행할 수 있다는 것입니다.
이들은 Grabcut Segmentation Algorithm을 이용합니다. Grabcut에 대해서는 더 자세하게 말씀드리지는 않겠습니다.
Grabcut은 간단히 말해 interactive segmentation algorithm 입니다.
이 Saliency Map과 Grabcut을 잘 조합하면 이미지 내에서 객체를 Segmentation할 수 있습니다.
아주 멋진 아이디어입니다. 하지만 그렇게 잘 되지는 않습니다.
supervision을 가지고 학습을 시키는 네트워크에 비해서는 훨씬 더 안좋습니다.
실용적인지는 잘 모르겠지만 작동한다는 것 자체가 정말 놀랍습니다.
supervision으로 segmentation을 학습시킨 모델보다는 훨씬 안좋지만 말이죠
또 다른 아이디어로는 guided back propagation이 있습니다.
이번에 할 질문은, 어떤 한 이미지가 있을 떄
이제는 클래스 스코어가 아니라 네트워크의 중간 뉴런을 하나 고릅니다.
그리고 입력 이미지의 어떤 부분이, 내가 선택한 중간 뉴런의 값에 영향을 주는지를 찾는 것이죠
이 경우에도 앞서 했던 방법처럼 Saliency Map을 만들어볼 수 있을 것입니다.
이 경우에는 이미지의 각 픽셀에 대한 "클래스 스코어"의 그래디언트를 계산하는 것이 아니라
입력 이미지의 각 픽셀에 대한 네트워크 중간 뉴런의 그레디언트를 계산합니다.
이를 통해 어떤 픽셀이 해당 뉴런에 영향을 주는 지 알 수 있습니다.
이 경우에도 평범한 back propagation을 이용합니다.
하지만 back propagation 과정에서 조금의 트릭을 가미하면 조금 더 깨끗한 이미지를 얻을수 있습니다.
이를 "guided back propagation" 이라고 합니다. Zeilerand Fergus의 2014년 논문입니다.
이번 시간에 이에 대해 더 깊게는 들어가지 않겠지만
이 방법(guided backprop)은 backprop 시 ReLU를 통과할 때 조금의 변형을 가해줍니다.
ReLU의 그레디언트의 부호가 양수 이면 그대로 통과시키고 부호가 음수이면 backprop하지 않는 방법입니다.
이로인해 전체 네트워크가 실제 그레디언트를 이용하는 것이 아니라 "양의 부호인 그레디언트" 만을 고려하게 됩니다.
이 방법이 왜 좋은지는 해당 논문을 각자 읽어보시기 바랍니다.
실험 결과를 보면, guided backprop이 그냥에 비해 훨씬 더 선명하고 좋은 이미지를 얻을 수 있음을 알 수 있습니다.
이 이미지들은 입력 이미지에 어떤 픽셀들이 특정 뉴런에 영향을 미치는지를 알려줍니다.
앞서 슬라이드에서 "maximally activating patches" 파트에서 이와 비슷한 시각화기법을 살펴봤었습니다.
"maximally activating patches" 기법 외에도
"guided backpropagation" 이라는 방법을 통해서 패치의 어떤 부분이 뉴런에 영향을 미치는지 알 수 있습니다.
맨 상당의 예를 살펴봅시다. 이미지들을 살펴보면 이 뉴런이 아마도 둥그런 것들을 찾고있음을 짐작해볼 수 있습니다.
guided backprob 결과(왼쪽)를 살펴보면 방금 전 우리가 짐작했던 직관을 어느정도 확신할 수 있습니다.
실제로 이미지 상의 둥근 부분들이 뉴런의 실제 값에 영향을 미치고 있음을 직접 확인할 수 있기 때문입니다.
이렇게 guided backprob은 중간 레이어가 무엇을 찾고 있는지를 이해하기 위한 영상을 합성하는데 아주 유용합니다.
하지만 guided backprob이나 saliency maps을 계산하는 방법들은 고정된 입력 이미지에 대한 연산을 수행할 뿐입니다.
이 방법들은 "고정된" 입력 이미지, 또는 입력 패치의 어떤 부분이 해당 뉴런에 영향을 미치는지를 말해줍니다.
그렇다면 입력 이미지에 의존적이지 않은 방법은 없을까요?
해당 뉴런을 활성화시킬 수 있는 어떤 "일반적인" 입력 이미지가 있을까? 란 질문을 할 수 있습니다.
이에 대한 질문은 "Gradient ascent" 라는 방법이 해답을 제시해줄 수 있습니다.
우리는 지금까지 Loss를 최소화시켜 네트워크를 학습시키기 위해 Gradient decent를 사용했습니다.
하지만 여기에서는 네트워크의 가중치들을 전부 고정시킵니다.
그리고 Gradient ascent를 통해 중간 뉴런 혹은 클래스 스코어를 최대화 시키는 이미지의 픽셀들을 만들어냅니다.
Gradient ascent는 네트워크의 가중치를 최적화하는 방법이 아닙니다. 가중치들은 모두 고정되어 있습니다.
대신 뉴런, 또는 클래스 스코어가 최대화될 수 있도록 입력 이미지의 픽셀 값을 바꿔주는 방법입니다.
이 방법에는 regularization term이 필요합니다.
우리는 지금까지 regularization terms의 역할을 가중치들이 학습 데이터로의 과적합을 방지하기 위함으로 배웠습니다.
이 경우에도 유사합니다. 생성된 이미지가 특정 네트워크의 특성에 완전히 과접합 되는 것을 방지하기 위함입니다.
regularization term을 추가함으로서, 우리는 생성된 이미지가 두 가지 특성을 따르길 원하는 것입니다.
하나는 이미지가 특정 뉴런의 값을 최대화시키는 방향으로 생성되길 원하는 것이고
그리고 다른 하나는 이미지가 자연스러워 보여야 한다는 것입니다.
생성된 이미지가 자연 영상에서 일반적으로 볼 수 있는 이미지이길(statistics) 원하는 것입니다.
이런 류의 regularization term의 목적은 생성된 이미지가 비교적 자연스럽도록 강제하는 역할입니다.
앞으로 다양한 regulaizer들을 살펴보겠습니다.
Gradient Ascent는 비교적 간단한 방법입니다. 과제 3에서 여러분이 직접 구현해보실 수 있을 것입니다.
Gradient Ascent를 위해서는 초기 이미지가 필요합니다. 이 이미지는 zeros, uniform, noise 등으로 초기화시켜줍니다.
초기화를 하고나면 이미지를 네트워크에 통과시키고 여분이 관심있는 뉴런의 스코어를 계산합니다.
그리고 이미지의 각 픽셀에 대한 해당 뉴런 스코어의 그레디언트를 계산하여 back prop을 수행합니다.
여기에서는 Gradient Ascent를 이용해서 이미지 픽셀 자체를 업데이트합니다. 해당 스코어를 최대화시키려 하겠죠
이 과정을 계속 반복하고나면 아주 멋진 이미지가 탄생합니다.
여기에서도 이미지에 대한 regularizer를 언급하지 않을수 없습니다.
여기에서는 단순하게 생성된 이미지에 대한 L2 norm을 계산해서 더해줍니다.
사실 L2 norm을 추가하는 것 자체에 큰 의미가 있는 것은 아닙니다.
Gradient Ascent와 같은 이미지 생성과 관련된 방법들의 초창기 문헌에서 종종 보이는 regularizer 중 하나일 뿐입니다.
이 네트워크를 학습시켜보면, 가령 왼쪽 상당의 덤벨의 스코어를 최대화시키는 이미지가 생성됩니다.
그리고 생성된 이미지를 살펴보면
잘 안보이실 수도 있지만, 여러 덤벨 모양이 생성되었음을 알 수 있습니다.
여러 덤벨들이 이곳 저곳에 중첩되어 있는 모양입니다.
그리고 컵의 생성된 이미지를 보면 아주 다양한 컵들이 충첩되어 있는 이미지를 볼 수 있습니다.
달마시안의 예가 정말 끝내줍니다.
달마시안의 특징이라고 할 수 있는 검정/흰색 반점 무늬를 볼 수 있습니다.
레몬의 경우에는 얼룩 얼룩한 노란색이 보입니다.
여기 몇 가지 예제가 더 있습니다. 거위의 경우도 정말 놀랍습니다.
키트 여우(kit fox)도 정말 키트 여우같아 보입니다.
질문 있나요?
질문은 "왜 이미지들이 무지개 색인지" 입니다.
이 시각화 방법을 이용해서 실제 색상을 시각화하려면 상당히 까다롭습니다.
실제 모든 이미지들은 0에서 255 사이의 값들로 이루어져야 합니다.
이는 constrained optimization 문제입니다.
하지만 Gradient ascent와 같은 일반적인 방법들은 제약조건이 없는(unconstrained) 경우입니다.
따라서 여러분이 Projected gradient descent 와 같은 알고리즘을 사용하고 마지막에 rescale한 경우라면
시각화 할 때 나타나는 색상과 관련해서는 너무 크게 신경쓸 필요 없습니다.
질문 있나요?
질문은 "아무 regularizer도 사용하지 않으면 어떻게 되는지" 입니다.
그렇게 해도 클래스 스코어를 최대화시키는 어떤 이미지가 생성되기는 할 것입니다.
하지만 그 이미지는 아무것도 아닌 것 처럼 보일 것입니다. 램덤 노이즈처럼 보일 뿐입니다.
그렇긴 해도 그 이미지 자체가 가지는 아주 흥미로운 특징이 있습니다. 이는 나중에 더 자세히 배울 것입니다.
어쩃든 이 이미지를 가지고는 네트워크가 어떤 것들을 찾고 있는지를 이해하기는 힘듭니다.
따라서 이를 위해서는 regularizer를 추가해서 이미지가 조금 더 자연스럽게 생성되도록 하는 편이 좋습니다.
질문 있나요?
질문은 "multimodality를 다루는 다른 방법은 없는지"입니다. (클래스 내에서도 다양한 mode가 있음.)
당연히 있습니다. 현재 시각화에 대한 본격적인 이야기는 이제 시작입니다.
시각화의 다른 접근법들은 regularizer를 더욱 향상시키고 이미지를 더 잘 시각화시키는 방법에 관한 것입니다.
Jason Yesenski, et al의 논문이 있습니다. 이들은 아주 인상적인 regularizers를 추가했습니다.
L2 norm constraint은 여전히 있습니다.
그리고 최적화 과정에 이미지에 주기적으로 가우시안 블러를 적용합니다.
그리고 주기적으로 값이 작은 픽셀들은 모두 0으로 만듭니다.
낮은 기울기의 픽셀 값 중 일부는 0으로 설정됩니다. 그레디언트가 작은 값들도 모두 0으로 만듭니다.
이는 일종의 projected Gradient descent 라고 볼 수 있습니다.
생성된 이미지를 더 좋은 특성을 가진 이미지 집합으로 주기적으로 매핑시키는 방법입니다. (밑에 세가지 방법으로)
가령 가우시안 블러와 같은 스무딩 연산을 통해서죠
이 방법을 이용하면 훨씬 더 보기 좋은 이미지를 생성할 수 있습니다. 훨씬 더 깔끔합니다.
홍학은 조금 더 홍학처럼 생겼습니다. 딱정벌레도 더 잘 보입니다.
검은 백조도 검은 백조처럼 잘 보입니다.
그 중에 당구대가 상당히 인상적입니다. 확실히 당구대의 구조가 선명합니다.
이처럼 조금 괜찮은 regularizer들을 추가하게 되면 생성되는 이미지가 조금 더 깔끔해질 수 있습니다.
이 과정은 최종 스코어에만 적용하는게 아니라 중간 뉴런에도 적용해볼 수 있습니다.
"당구대" 클래스의 스코어를 최대화시키는 것이 아니라 중간의 뉴런을 최대화시키는 이미지를 생성해볼 수도 있습니다.
질문 있나요?
질문은 "이 예제의 네가지 이미지가 무엇인지" 입니다.
우선 이 이미지는 처음에 램덤 초기화된 이미지입니다.
따라서 이 네 개의 이미지들은 서로 다르게 램덤으로 초기화된 입력 이미지입니다.
다시 수업으로 돌아가서, 앞서 클래스 스코어에 적용했던 과정은 네트워크의 중간 뉴런을 최대화시키는 과정에 동일하게 적용됩니다.
이를 통해서 중간 뉴런이 무엇을 찾고있는지 짐작해볼 수 있습니다.
가령 네번째 레이어의 경우에는 나선형의 무언가를 찾고있는 것 같습니다.
또 어떤 뉴런은 애벌레를 찾는 것 같아 보입니다. 정확이 무엇인지는 구별하기 힘들군요
여기 예제 이미지가 큰 이미지일수록 receptive fileds 가 더 큰 뉴런들입니다.
Receptive field가 클수록 이미지 패치 내에 더 큰 곳을 볼 수 있습니다.
이런 뉴런들은 입력 이미지에서 더 큰 구조와 더 복잡한 패턴을 찾는 경향이 있습니다.
아주 멋집니다.
사람들이 이 시각화 방법이 이미지의 특징들을 잘 살리는 것에 아주 열광했습니다.
방금 전 누군가가 질문해주신 multimodality 를 이 논문에서 아주 잘 다루고 있습니다.
이 논문에서는 최적화 과정 속에 multimodality를 아주 명시적으로 다루고 있습니다.
각 클래스마다 클러스터링 알고리즘을 수행합니다.
한 클래스 내 서로 다른 모드들 끼리 다시 한번 클래스가 나뉩니다. 그리고 나뉜 모드들과 가까운 곳으로 초기화를 해주는 것이죠
이 방법을 통해서 multimodality를 다룰 수 있는 것입니다.
직관적으로 보면, 가령 여기 있는 여덟개의 이미지는 모두 식료품점(grocery store) 입니다.
가장 상위의 이미지들은 선반 위에 전시된 물건들을 클로즈업 한 것 같아 보입니다.
이들의 레이블은 "식료품 점" 입니다.
그리고 하단의 이미지들은 사람들이 식료품점을 돌아다니고 있는 모슴인 것 같습니다.
이 또한 식료품점으로 레이블링됩니다.
하지만 이 둘은 아주 다르게 생겼습니다.
많은 클래스들이 이렇게 multimodality를 가지고 있습니다.
이미지를 생성할 때 이런 식으로 multimodality를 명시하게 되면 아주 좋은 (다양한) 결과를 얻을 수 있게 됩니다.
예제를 조금 더 살펴보도록 하죠. 여러 클래스의 이미지를 합성해 보았습니다.
피망, 카르둔, 딸기, 잭오랜턴 등을 볼 수 있습니다. 이미지가 아주 잘 생성되었습니다.
다음 장은 깊게 들어가지는 않겠습니다만 이 방법은 훨씬 더 놀라운 방법입니다.
이 방법은 이미지를 이쁘게 생성해 내기 위해서 훨씬 더 강력한 사전 정보(prior)를 이용합니다.
여기 보이는 이미지들이 모두 ImageNet의 특정 클래스를 최대화하는 이미지를 생성해 낸 것입니다.
기본 아이디어는 입력 이미지의 픽셀을 곧장 최적화하는 것 대신에 FC6를 최적화하는 것입니다.
이를 위해서는 feature inversion network 등을 사용해야 하지만 자세히 들어가진 않겠습니다.
관심있으신 분들은 논문을 읽어보시기 바랍니다. 아주 놀라운 방법입니다.
요점은 이런 이미지 생성 문제에서 사전 지식(priors)를 추가하게 된다면
아주 리얼한 이미지를 만들어낼 수 있다는 것입니다.
이 방법도 여러분들이 시도해볼만한 아주 좋은 방법이 될 수 있습니다. 어쨋건,
이미지 픽셀의 그레디언트를 이용해서 이렇게 이미지를 합성하는 방법은 아주 강력합니다.
이를 통해 시도해볼 수 있는 아주 재미있는 것은 바로 네트워크를 속이는 이미지(fooling image)를 만드는 것입니다.
우선 아무 이미지나 하나 고릅니다. 가령 코끼리 이미지를 골랐다고 해봅시다.
그리고 네트워크가 이 이미지는 코알라 라고 분류하도록 이미지를 조금씩 바꿉니다.
이렇게 코끼리 이미지를 조금씩 바꾸다보면 네트워크는 이 이미지를 코알라라고 분류해 버립니다.
여러분이 혹시라도 코끼리가 갑자기 귀여운 귀를 가진 코알라로 변신하는 모습을 상상할 지 모르곘습니다만
사실은 그런 일은 일어나지 않습니다. 이점이 아주 놀라운 점입니다.
코끼리 사진을 가지고 코알라로 분류하도록 이미지를 바꿔보면
실제로는 두 번째 이미지 처럼 보입니다. 네트워크는 두 번째 이미지를 코알라로 분류합니다. 우리에게는 별반 차이가 없습니다.
아주 수상하기도(fishy) 하면서 놀랍기도 합니다.
밑에 예제가 하나 더있습니다. 배 인것 같은데 ImageNet 클래스로는 Schooner(범선) 입니다.
이제 네트워크가 아이팟으로 분류하도록 합니다.
두 번째 이미지를 보면 우리에게는 똑같이 배인데 네트워크는 아이팟이라고 인식하고 있습니다.
두 이미지 사이의 픽셀 값의 차이는 거의 없습니다.
우리는 픽셀 값의 차이에서 코알라나 아이팟의 특징이라고는 찾아볼 수 없습니다.
그저 랜덤한 패턴의 노이즈로 보일 뿐입니다. 그렇다면 질문은 "무슨 일이 일어난 것일까요?", "어떻게 이런게 가능한 것일까요?"
굿조만한 우리 수업 게스트로 Ian Goodfellow를 초청할 예정입니다.
Ian Goodfellow가 와서 이와관련한 현상을 조금 더 자세히 설명해 줄 것입니다. 아주 재밌을 것입니다.
하지만 여기에서는 더 이상 언급하지 않겠습니다. 왜냐하면 여러분들의 과제이기 떄문이죠
질문 있나요?
질문은 "학습 데이터로도 네트워크를 속일 수 있는지" 입니다.
이와 관련된 모든 것들은 Ian이 와서 소개해줄 것입니다. Ian Goodfellow가 와서 강연 내내 다룰 것입니다.
질문 있나요?
질문은 "왜 우리가 이딴거(stuff)에 관심을 가져야 하는 것인지"
제가 질문을 조금 거칠게 표현했습니다. 죄송합니다.
질문은 "중간 뉴런을 이해하는 것이 어떻게 최종 클래스 분류를 이해하는데 도움을 줄 수 있는지" 입니다.
사실 이런 식으로 중간 레이어를 시각화하는 방법들은 딥러닝의 비판에 대한 반응에서 유래합니다.
딥러닝의 비판이라 함은 "딥러닝 이라는 블랙박스를 가진건 알겠어,
- 그리고 그걸 그레디언트로 잘 학습시켜서 좋은 결과가 나오는건 알겠는데, 사실 결과를 믿진 못하겠어
딥러닝의 결과가 어떻게 나왔는지를 당신조차 이해할수 없잖아?" 와 같은 질문이죠
이런 많은 시각화 기법들은 왜 딥러닝이 분류 문제를 더 잘 푸는지를 사람들이 이해하기 위해 고안되었습니다.
가령, 딥러닝이 아닌 다른 기계학습 기법들을 생각해보면
가령 선형 모델의 경우가 일반적으로 해석하기 훨씬 더 수월합니다.
각 가중치를 보고 입력 특징들 중 어떤 부분이 얼마나 모델이 결정을 내리는데 영향을 미치는지 해석하기 용이합니다.
Random forest와 같은 dectision tree를 보면 말이죠.
이런 기계학습 기법들이 블랙박스인 CNN보다는 훨씬 더 자연스럽고 해석하기도 쉽습니다.
딥러닝에 대한 앞서 언급한 비판들에 대한 대안으로 시각화 기법들이 등장했습니다. "그래 모델이 복잡하긴 하지,
하지만 들춰보면 해석 가능한 것들이 있다구!" 라고 말하는 것입니다.
딥러닝 모델이 아무렇게나 분류하는 것이 아니라 의미있는 행동을 하고 있음을 증명하려는 것입니다.
이미지에 그레디언트를 업데이트하는 방식으로 가능한 재미있는 아이디어가 하나 더 있습니다. "DeepDeram" 입니다.
작년 Google에서 나온 아주 재미있는 블로그 포스팅이 있었습니다.
DeepDream의 "과학적 가치"의 측면에서 보자면 그저 "재미" 만을 위한 것입니다.
DeepDream의 목적은 "재미있는 이미지를 만드는 것" 입니다.
부가적으로 모델이 이미지의 어떤 특징들을 찾고 있는지를 짐작할 수도 있습니다.
DeepDeram에서는 입력 이미지를 CNN의 중간 레이어를 어느정도 통과시킵니다.
그리고 back prop을 할 차례입니다.
해당 레이어의 그레디언트를 activation 값으로 설정합니다.
그리고 back prob을 하여 이미지를 업데이트합니다. 이 과정을 계속 반복합니다.
네트워크에 의해 검출된 해당 이미지의 특징들을 증폭시키려는 것으로 해석할 수 있습니다.
해당 레이어에 어떤 특징들이 있던지 그 특징들을 그레디언트로 설정하면
이는 네트워크가 이미지에서 이미 뽑아낸 특징들을 더욱 증폭시키는 역학을 하는 것입니다.
그리고 이는 해당 레이어에서 나온 특징들의 L2 norm을 최대화시키는 것으로 볼 수 있습니다.
DeepDream의 코드는 아주 심플합니다. 이는 여러분의 과제에 포함되어 있습니다.
여러분이 앞으로 과제를 통해 접하겠지만 여기에는 몇 가지 트릭이 존재합니다.
트릭 중 하나는 그레이언트를 계산하기에 앞서 이미지를 조금씩 움직이는 것입니다.(jitter)
원본 이미지를 그대로 네트워크에 통과시키는 것 대신에 이미지를 두 픽셀 정도 이동시킵니다.
이는 regularizer 역할을 해서 자연스럽고 부드러운 이미지를 만들어줍니다.
그리고 여기에 L1 Normalization도 들어갑니다. 이는 이미지 합성 문제에서 아주 유용한 트릭입니다.
그리고 픽셀 값을 한번 클리핑(Clipping) 해주기도 합니다. 이미지라면 값이 0-255 사이에 있어야만 합니다.
이는 일종의 projected gradient decent인데 실제 이미지가 존재할 수 있는 공간으로 매핑시키는 방법입니다.
이렇게 하늘 이미지를 가지고 알고리즘을 수행시키면 이처럼 아주 재미있는 결과를 보실 수 있습니다.
하늘에 조그만한 특징들이 보이실 것입니다. 이들을 앞선 과정을 통해 증폭된 것들입니다.
돌연변이 동물같은 것들이 나타났습니다. 나선 모양의 것들도 나타났습니다.
다양한 종류의 건축물과 자동차도 나타났습니다. 모든 것들이 아주 흥미로운 결과입니다.
나타난 특징들 중에 사람들이 이름을 지어낸 것들도 있습니다.
아주 많이 나타난 것 중 하나가 "Admiral dog" 입니다.
"돼지 달팽이 (pig snail), "낙타 새"(Camel-bird), "개 물고기"(dog-fish) 도 있습니다.
이 모든것들이 아주 흥미롭습니다만, 이러한 시각화에 "개" 가 아주 빈번하게 등장한다는 것은
이 네트워크를 학습시킨 데이터와 관련이 있습니다.
이 네트워크는 ImageNet Classification 데이터셋으로 학습시켰습니다. 1000개의 카테고리가 있습니다.
그런데, 그 중 200개의 카테고리가 개입니다.
따라서 시각화된 결과에 "개"와 관련된 것들이 자주 나오는 것은 당연합니다.
그리고 다른 레이어를 가지고 만들어보면 색다른 결과를 보실 수도 있습니다.
이 예제의 경우 더 얕은 층의 레이어로 만든 이미지입니다. 앞서 보여드린 예제가 조금 더 깊은 층의 레이어로 만들었었죠
더 얕은 층으로 만들어보면, 엣지나, 소용돌이 무늬와 같은 것들을이 보입니다.
얕은 레이어로 DeepDream을 수행하면 보이는 것들입니다.
DeepDream에 멀티 스케일을 가미해서 오랫동안 돌려보면 다음과 같은 아주아주 놀라운 것들을 볼 수 있습니다.
여기에서는 멀티 스케일 프로세싱을 수행합니다. 작은 이미지로 DeepDream을 수행하고 점점 이미지 크기를 늘려나갑니다.
이런 식으로 점점 더 큰 이미지에 DeepDream을 수행하는 반복적인 과정을 거치는데,
가장 큰 최종 스케일로 수행하고 나면 다시 처음부터 이 과정을 반복 수행합니다.
그 결과 이런 놀라운 이미지를 얻을 수 있습니다.
지금 보시는 이미지는 ImageNet으로 학습시킨 네트워크로 만든 이미지입니다.
다른 데이터셋으로도 만들어 볼 수 있습니다. 가령 MIT Paces Dataset으로도 해볼 수 있겠죠
1,000 카테고리의 객체(ImageNet) 대신에 200가지의 다양한 장면을 가진 데이터셋입니다.
이 데이터셋에는 가령 침실, 부엌 과 같은 장면이 있습니다.
MIT place로 학습시킨 네트워크를 가지고 DeepDream을 수행하면, 이와 같은 멋있는 시각화 이미지를 얻을 수 있습니다.
이제는 "개 달팽이, Admiral dogs" 와 같은 것들 대신에 일본식 건축물의 지붕과 같은 모양이라던지
다양한 "다리(bridges)", "산맥(mountatin ranges" 과 같은 것들이 보입니다.
아주 멋있고 아름다운 이미지들입니다.
DeepDream의 코드를 Google이 온라인에 공개하였으니 여러분만의 아름다운 그림을 만들어보면 좋겠습니다.
질문 있나요?
질문은 "그레디언트를 어디에서 가져오는지" 입니다.
앞서 말씀드렸듯, 1/(x^2)가 있을때 activation에 대한 그레디언트는 x입니다.
따라서 그레디언트를 보낼때 activation 값 자체를 보내게 되면, 1/(x^2) 의 그레디언트를 계산하는 것과 동치입니다.
그리고 이는 해당 레이어의 특징들(activations)의 norm을 최대화시키는 것과 동치입니다.
하지만 대부분의 실제 구현은 이를 명시적으로 계산하지는 않고 그레디언트만 뒤로 보내줍니다.
Feature inversion 이라는 아주 유용한 개념이 있습니다.
이 방법 또한 네트워크의 다양한 레이어에서 이미지의 어떤 요소들을 포착하고 있는지를 짐작할 수 있게 해줍니다.
방법은 다음과 같습니다. 어떤 이미지가 있고, 이 이미지를 네트워크에 통과시킵니다.
그리고 네트워크를 통과시킨 특징(activation map)을 저장해둡니다.
그리고 이제는 이 특징(activation map) 만 가지고 이미지를 재구성해 볼 것입니다.
해당 레이어의 특징 벡터로부터 이미지를 재구성해보면, 이미지의 어떤 정보가 특징 벡터에서 포착되는지를 짐작할 수 있을 것입니다.
이 방법에서 또한 regularizer를 추가한 gradient ascent를 이용합니다.
스코어를 최대화시키는 것 대신, 특징 벡터간의 거리를 최소화시키는 방법을 이용합니다.
기존에 계산해 놓은 특징 벡터와, 새롭게 생성한 이미지로 계산한 특징벡터 간의 거리를 측정하는 것입니다.
여러분이 과제에서 보겠지만, 여기 사람들이 자주 사용하는 regularizer인 total vatication이 있습니다.
Total variation regularizer은 상하좌우 인접 픽셀 간의 차이에 대한 패널티를 부여합니다.
생성된 이미지가 자연스러운 이미지가 되도록 해줍니다.
Feature inversion을 통한 시각화 예제를 살펴봅시다. 왼쪽은 원본 이미지입니다.
코끼리 이미지와 과일 이미지가 있습니다.
이 이미지를 VGG-16에 통과시켜봅시다.
그리고 특징 맵을 기록하고, 기록된 특징 맵과 부합하도록 하는 새로운 이미지를 합성합니다.
다양한 레이어를 이용해서 합성한 이미지들을 통해서, 얼마나 많은 정보들이 저장되어 있는지를 짐작해 볼 수 있습니다.
가령 VGG-16 의 relu2_2를 거쳐서 나온 특징 벡터를 가지고 이미지를 재구성해보면
이미지가 거의 완벽하게 재구성됨을 알 수 있습니다.
이를 통해, relu2_2 에서는 이미지 정보를 엄청 많이 날려버리지는 않는다는 사실을 알 수 있습니다.
자 그럼 이제 네트워크의 조금 더 깊은 곳을 살펴봅시다. relu4_3 과 relu5_1을 가지고 재구성해 보겠습니다.
재구성된 이미지를 보면 이미지의 공간적인 구조는 잘 유지하고 있다는 것을 알 수 있습니다.
재구성된 이미지만 봐도 코끼리인지, 바나나인지, 사과인지 우리 눈으로도 구별할 수 있습니다.
하지만 디테일은 많이 죽었습니다. 정확히 어떤 픽셀인지, 어떤 색인지, 텍스터가 정확히 어떤지를 알아보기 힘듭니다.
그런 낮은 레벨의 디테일들은 네트워크가 깊어질수록 손질됨을 알 수 있습니다.
이를 통해서, 네트워크가 깊어질수록 픽셀 값이 정확히 얼마인지 와 같은 저 수준의 정보들은 전부 사라지고, 대신에
색이나 텍스처와 같은 미세한 변화에 더 강인한 의미론적 정보들만을 유지하려 하는 것일지 모릅니다.
우리는 지금까지 계속 Style transfer를 배우기 위한 준비단계에 있습니다.
Style transfer와 feature inversion 외에도 텍스처 합성과 관련된 문제들도 살펴볼 필요가 있습니다.
텍스처 합성 문제는 컴퓨터 그래픽스 분야에서는 아주 오래된 문제입니다.
문제는, 가령 여기 보이시는 비늘 무늬와 같은 입력 텍스처 패치가 있을 때, 동일한 텍스처인 더 큰 패치를 생성하는 것입니다.
가령 여기 보시는 그림과 같이 입력 패치와 비슷한 비늘 패턴을 가진 더 큰 이미지를 생성하는 것입니다.
다시 말씀드리지만 텍스처 합성은 컴퓨터 그래픽스에서 아주 오래된 문제입니다.
nearest neighbor를 통한 텍스처 합성 방법들도 상당히 좋은 편입니다.
이 방법에는 신경망을 사용하지 않죠
이 간단한 알고리즘은 신경망 대신에 scan line을 따라서 한 픽셀씩 이미지를 생성해 나가는 방식입니다.
이 방법은 현재 생성해야 할 픽셀 주변의 이미 생성된 픽셀들을 살펴봅니다.
그리고 입력 패치에서 가장 가까운 픽셀을 계산하여 입력 패치로부터 한 픽셀을 복사해 넣는 방식이죠
더 자세히 알 필요는 없습니다. 텍스처 합성 문제를 위한 고전적인 방법들이 아주 많다는 사실만 알아두시면 됩니다.
기본적으로 텍스처 합성은 신경망 없이도 할 수 있습니다.
앞서 말씀드린 고전적인 방법들은 간단한 텍스처를 합성하는데는 큰 문제가 없습니다.
하지만 조금 더 복잡한 텍스처에서는 상황이 조금 다릅니다. 단순하게 입력 패치에서 복사하는 방식은 잘 동작하지 않습니다.
2015년에 신경망을 활용해서 텍스처 합성 문제는 푸려는 시도가 처음 있었습니다.
이 방법은 우리가 앞서 살펴본 특징 맵을 이용한 gradient ascent 방법도 상당히 유사합니다.
이 방법은 Neural texture synthesis 를 구현하기 위해서 Gram matrix라는 개념을 이용합니다.
이 방법에서는, 가령 여기 입력 텍스처로 자갈 사진이 있습니다.
이 사진을 네트워크에 통과시킨 후, 네트워크의 특정 레이어에서 특징 맵을 가져옵니다.
이렇게 가져온 특징 맵의 크기는 C x H x W 일 것입니다.
H x W 그리드는 공간 정보는 가지고 있습니다.
H x W 의 한 점에 있는 C차원 특징 벡터는 해당 지점에 존재하는 이미지의 특징을 담고 있다고 할 수 있습니다.
이제 이 특징 맵을 가지고 입력 이미지의 텍스트 기술자(descriptor)를 계산할 것입니다.
우선 특징 맵에서 서로 다른 두 개의 특징 벡터를 뽑아냅니다. (빨간 색, 파란 색)
각 특징 열 벡터는 C차원 벡터입니다.
이 두 벡터의 외적(outer product)을 계산해서 C x C 행렬을 만듭니다.
이 C x C 행렬은 이미지 내 서로 다른 두 지점에 있는 특징들 간의 co-occurrence를 담고 있습니다.
가령 C x C 행렬의 (i, j) 번째 요소의 값이 크다는 것은 두 입력 벡터의 i번째, j번째 요소가 모두 크다는 의미입니다.
이를 통해 서로 다른 공간에서 동시에 활성회되는 특징이 무엇인지 2차 모멘트를 통해 어느정도 포착해 낼 수 있는 것입니다.
이 과정을 H x W 그리드에서 전부 수행해주고, 결과에 대한 평균을 계산해보면 C x C Gram matrix를 얻을 수 있습니다.
그리고 이 결과를 입력 이미지의 텍스처를 기술하는 텍스처 기술자로 사용합니다.
Gram matrix의 흥미로운 점은 공간 정보를 모두 날려버렸다는 것입니다.
이미지의 각 지점에 해당하는 값들을 모두 평균화 시켰기 떄문입니다.
공간 정보를 다 날려버린 대신에 특징들 간의 co-occurrence 만을 포착해 내고 있습니다.
때문에 gram matrix는 텍스처 기술자로 아주 제격입니다.
또한 계산도 아주 효율적입니다.
C x H x W 차원의 3차원 텐서가 있다고 해도 행렬을 C x (HW)로 바꾼 다음에 한 번에 계산할 수 있습니다. 매우 효율적입니다.
혹시, 왜 제대로된 공분산 행렬을 쓰지 않고 이런 허접한 gram matrix를 사용하는지 궁금하실 수도 있습니다.
물론 공분산 행렬을 써도 무방하고, 실제로 동작도 잘 합니다. 하지만 공분한 행렬을 계산하는 것 자체가 비용이 너무 큽니다.
따라서 실제로 사람들은 공분산 행렬 보다는 gram matrix를 선호하는 편입니다.
자 이제 텍스처 기술자를 만들었으니 이미지를 생성할 차례입니다. 이는 gradient ascent procedure와 유사한 과정을 거칩니다.
텍스처 합성도, 앞서 슬라이드에서 접했던 특징 재구성(feature reconstruction)와 유사합니다.
다만 입력 이미지의 특징맵 전체를 재구성하기 보다는 gram matrix를 재구성하도록 하는 것입니다.
실제로 거치는 단계는, 우선 pretrained model를 다운로드 받습니다. feature inversion에서 했던 것 처럼.
많은 사람들이 VGG 네트워크를 선호합니다.
그리고 이미지를 VGG에 통과시키고 다양한 레이어에서 gram matrix를 계산합니다.
그리고 생성해야 할 이미지를 랜덤으로 초기화시키고, 그 다음 과정 부터는 gradient ascent와 유사합니다.
다시, 우선 이미지를 VGG에 통과시킵니다. 그리고 여러 레이어에서 gram matrix를 계산합니다.
그리고 원본 이미지와 생성된 이미지의 gram matrix 간의 차이를 L2 norm을 이용해 Loss로 계산합니다.
그리고 Loss를 backprob을 통해 생성된 이미지의 픽셀의 그레디언트를 계산합니다.
그리고 gradient ascent 를 통해 이미지의 픽셀을 조금씩 업데이트 합니다.
이 단계을 여러번 반복합니다. 다시 앞 단계로 가서 gram matrix를 계산하고, Loss를 계산하고 backprob합니다.
이 과정을 거치면 결국 입력 텍스처와 유사한 아주 잘 텍스처를 만들어낼 수 있습니다.
NIP'15에 실린 논문은 독일의 한 연구소에서 나왔습니다. 텍스처 합성 결과가 아주 뛰어납니다.
맨 위 이미지를 보시면 네가지의 서로 다른 입력 텍스처를 보실 수 있습니다.
그리고 아래 쪽은 gram matix를 이용한 텍스터 합성을 보여줍니다.
pretrained CNN의 다양한 레이어에서 gram matrix 를 계산한 결과입니다.
얕은 레이어에서의 결과를 보면, 얼룩 얼룩한 이미지가 색상은 잘 유지하고 있지만 공간적인 구조는 잘 살리지 못합니다.
레이어가 더 깊어질수록, 이미지의 더 큼지막한 패턴들을 아주 잘 재구성해 내는 것을 보실 수 있습니다.
가령 여기 자갈이나 크렌베리를 보면 아주 잘 만들어졌죠
결과가 상당히 좋습니다. 입력 패치의 패턴과 아주 유사한 새로운 이미지를 아주 잘 합성해 낼 수 있습니다.
앞서 보여드린 고전적인 픽셀 기반의 방법과는 확연히 다른 결과들을 보실 수 있습니다.
질문 있나요?
질문은 "보통 Loss를 어느 레이어에서 계산하는지" 입니다.
일반적으로는 gram matrix를 다양한 레이어에서 계산하고 가중 합을 통해 최종 loss를 구합니다.
현재 보시는 슬라이드의 경우에는, 각 레이어의 특징을 강조하기 위해서, 오로지 한 레이어로만 gram matrix를 계산한 것입니다.
이 논문 이후로 아주 놀라운 아이디어가 등장하게 됩니다.
이 텍스처 합성을 자갈이나 크렌베리가 아니라 예술작품에 적용하면 어떻게 될까요?
그래서, 예를 들어, 당신이...
자 우선, gram matrix를 이용한 텍스처 합성은 그대로 가져갑니다.
여기에 Starry night(Van Gogh) 이나 Muse(Picasso) 를 텍스처 입력으로 사용하면 어떻게 될까요?
이들을 입력 텍스처로 두고 같은 알고리즘을 수행합니다.
생성된 이미지를 보면, 이들은 예술 작품의 아주 흥미로운 부분들을 재구성해 내는 경향을 알 수 있습니다.
texture synthesis와 feature inversion 을 조합하면 아주 흥미로운 일이 벌어집니다.
아 아이디어가 바로 style transfer 입니다.
Style transfer에서는 입력이 두가지입니다.
Content Image는 네트워크에게 우리의 최종 이미지가 어떻게 "생겼으면 좋겠는지" 를 알려줍니다.
Style Image는 최종 이미지의 "텍스처가 어땠으면 좋겠는지" 을 알려줍니다.
최종 이미지는 content image의 feature reconstruction loss도 최소화하고(1),
Style image의 gram matrix loss도 최소화하는 방식으로 최적화하여 생성해 냅니다.
이 두가지 Loss를 동시에 활용하면, style image 스러운 화풍의 content image가 생성됩니다.
아주 멋있는 결과입니다. 아주 아름다운 이미지를 얻을 수 있습니다.
네트워크에 content/style 이미지를 네트워크에 통과시키고 gram matrix와 feature map을 계산합니다.
최종 출력 이미지는 랜덤 노이즈로 초기화시킵니다.
forward/backward를 반복하여 계산하고 gradient ascent 를 이용해서 이미지를 업데이트합니다.
수 백번정도 반복하면 아주 아름다운 이미지를 얻을 수 있게 됩니다.
제 github에 실제 구현이 있습니다. 사람들이 많이 사용하는데요, 아주 멋집니다.
Style Transfer는 DeepDream에 비해서 이미지를 생성할 때 컨트롤할 만한 것들이 더 많습니다.
DeepDream의 경우에는 어떤 것들을 만들어낼지 컨트롤할 만한 요소가 많이 부족합니다.
네트워크에 레이어와 반복 횟수정도만 조절하면 "개 달팽이(dog slug)"가 이미지 전체에 퍼질 뿐입니다.
반면 Style Transfer의 경우 원하는 결과를 만들기 위해 정밀 조절한 것들이 조금 더 많습니다.
동일한 content image라고 할지라도 다양한 style images 를 고르게 되면 전혀 다른 이미지들이 생성됩니다.
하이퍼파라미터도 자유롭게 조정할 수 있습니다. style/content loss의 joint loss이기 때문이죠
style/content loss간의 가중치를 조절하면, 내가 어디에 더 집중해서 만들 것인지를 조절할 수 있습니다.
또 다른 하이퍼파라이터도 존재합니다.
가령 gram matrix를 계산하기 앞서 style image를 리사이징 해서 넣어준다면
Style image로부터 재구성된 특징들의 스케일을 여러분 마음대로 조절할 수 있을 것입니다.
여기 보이는 이미지들은 다른 것들은 전부 같은 세팅이고 다만 style image의 사이즈만 달라진 경우입니다.
Style image의 사이즈를 조절하는 것이 조절할 수 있는 또 하나의 축이 될 수 있습니다.
또한 여러 장의 style images를 가지고 style transfer를 할 수도 있습니다.
동시에 여러 style loss의 gram matrix를 계산하는 것입니다. 결과도 아주 좋습니다.
앞서 DeepDream에서 multi-scale processing을 통해 아주 멋진 고해상도 이미지를 얻을 수 있었습니다.
multi-scale processing을 style transfer에도 적용해 볼 수 있습니다.
이 이미지는 Starry night로 랜더링된 4K Stanford 이미지입니다.
사실 고해상도 이미지를 만드는 것은 계산량이 상당합니다.
4K 이미지를 위해 GPU 네 개를 사용했습니다. 아주 비싼 연산입니다.
이는 동일한 content image를 가지고 다른 style image를 적용한 것입니다. 고해상도죠
또 다른 재밌는 방법도 있습니다. 사실 Style Transfer와 DeepDream을 조합해 볼 수도 있습니다.
content loss + style loss + deepdream loss( norm 최대화) 를 조합하는 것입니다.
결과는 다음과 같습니다. "개 달팽이(dog slug)" 가 사방에 퍼져있는 Van Gogh 그림입니다.
[웃음]
아주 재밌습니다.
Style Stranfer 알고리즘의 가장 큰 단점은 아주 느리다는 것입니다.
이런 이미지를 만들어 내려면 backward/forward를 아주 많이 반복해야 합니다.
게다가 앞서 보여드린 4K 이미지를 만드려면 메모리와 계산량이 엄청나게 큽니다.
엄청 좋은 GPU를 쓰더라도 이미지 한장을 만드는데 수십 분이 요소됩니다.
따라서 실제로 적용하기는 힘듭니다.
해결책이 있다면, Style tranfer를 위한 또 다른 네트워크를 학습시키는 것입니다.
2016년에 나온 논문입니다. 애초에 Style image를 고정시켜 놓습니다. 이 경우 Starry night 입니다.
이 방법은 합성하고자 하는 이미지의 최적화를 전부 수행하는 것이 아니라
Content image만을 입력으로 받아서 결과를 출력할 수 있는 단일 네트워크를 학습시키는 방법입니다.
이 네트워크의 학습 시에는, content/style loss를 동시에 학습시키고 네트워크의 가중치를 업데이트합니다.
학습은 몇 시간이 걸릴 수 있지만, 한번 학습시키고 나면 이미지를 네트워크에 통과시키면 결과가 바로 나올 수 있습니다.
이 코드는 온라인에 있습니다. 영상 퀄리티는 기존의 방법과 거의 유사하면서도, 몇천배 빠르게 동작합니다.
여러분이 보고계신 이 데모는 제가 웹캠으로 직접 돌려본 것입니다.
이 네트워크가 아주 효율적이기 때문에 좋은 GPU을 사용하면 네 가지 스타일을 동시에 돌려볼 수도 있을 것입니다.
러시아에서 나온 논문도 있습니다. 유사한 논문이고 결과도 아주 좋습니다.
알고리즘을 조금 변형한 방법도 있습니다.
앞서 보여드린 이 네트워크는 앞서 배웠던 세그멘데이션 네트워크와도 아주 유사하게 생겼습니다.
Sementic segmentation 에서는 다운 샘플링을 여러 번 진행하고 transposed conv로 업샘플링을 합니다.
Segmentic segmentation과 다른 점이라고는 출력이 RGB 이미지라는 점입니다.
그리고 네트워크 중간에 batch norm이 들어갑니다.
이 논문에서는 batch norm 대신에 instance norm을 사용해서 더 좋은 결과를 끌어냈습니다.
지금까지 말씀드린 방식들의 단점이 있다면 네트워크 하나당 하나의 Style Transfer 밖에 할 수 덦다는 점입니다.
다양한 Style을 위해서 서로 다른 네트워크를 만드는 일은 상당히 비용이 큰 작업입니다.
아주 최근에 Google 에서 나온 논문은, 하나의 네트워크로 다양한 Style을 생성해낼 수 있는 방법을 제안했습니다.
하나의 네트워크만 학습시켜서 다양한 Style result를 만들어낼 수 있는 방법입니다.
네트워크 입력으로 content image와 style image를 동시에 넣는 방식을 통해서 다양한 스타일을 만들어낼 수 있습니다.
이 네트워크 또한 실시간으로 동작할 수 있습니다.
동일한 알고리즘은 하나의 네트워크 만으로 실시간 style blending 또한 가능합니다.
네 가지 서로 다른 style을 학습시키면 이 네 가지 style을 섞어버릴 수도 있습니다.
이러한 종류의 real-time style transfer 방법들은 아주 다양한 응용이 가능하며 실제로 많이 사용되고 있습니다.
오늘 배운 내용을 요약해봅시다.
우리는 오늘 CNN representations을 이해할 수있는 다양한 방법들을 배웠습니다.
우선 activation 기반의 방법들이 있었습니다.
nearest neighbor, dimensionality reduction maximal patches, occlusion images 등이죠
Activation values를 기반으로 해당 특징이 무엇을 찾고있는지를 이해하는 방법이었습니다.
우리는 또한 gradient 기반의 방법도 배웠습니다.
gradients을 이용해서 새로운 이미지를 만들어내는 방법이었습니다.
saliency maps, class visualizations, fooling images, feature inversion이 있었죠
그리고 아주 멋있는 이미지들을 생성해내는 Style Transfer/DeepDream을 알아보았습니다.
다음 시간에는 unsupervised learning에 대해서 배워보겠습니다.
Autoencoders, Variational Autoencoders(VAE), generative adversarial networks(GAN) 을 배워보겠습니다.